﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows.Forms;

namespace ROrganizer.UI.Forms.Core
{
    public static class FormExtensions
    {
        public static void ExecuteAndWatch(this Form form, Action action)
        {
            FormExtensions.ExecuteInternal(form, action);
        }

        public static void ExecuteAndWatch<T>(this Form form, Action<T> action, T param)
        {
            FormExtensions.ExecuteInternal(form, () => action(param));
        }

        public static void ExecuteAndWatch<T1, T2>(this Form form, Action<T1, T2> action, T1 param1, T2 param2)
        {
            FormExtensions.ExecuteInternal(form, () => action(param1, param2));
        }

        public static void ExecuteAndWatch<T1, T2, T3>(this Form form, Action<T1, T2, T3> action, T1 param1, T2 param2, T3 param3)
        {
            FormExtensions.ExecuteInternal(form, () => action(param1, param2, param3));
        }

        public static bool SynchronizeInvocation<T>(this Form form, Action<object, T> handler, object sender, T args)
            where T : EventArgs
        {
            if (form.InvokeRequired)
                form.Invoke(handler, sender, args);

            return !form.InvokeRequired;
        }

        private static void ExecuteInternal(Form form, Action action)
        {
            try
            {
                action();
            }
            catch (TargetInvocationException ex)
            {
                FormExtensions.ProcessException(form, ex.InnerException);
            }
            catch (Exception ex)
            {
                FormExtensions.ProcessException(form, ex);
            }
        }

        public static void ProcessException(this Form form, Exception exception)
        {
            Action action = () => MessageBox.Show(form, exception.Message, form.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
            form.Invoke(action);
        }
    }
}
